/**
* @file SerialPortHandler.h in LiveGraph
* @author linfe
* @comment
* Create on 2022/9/30 22:09
* @version 1.0
**/

#ifndef LIVEGRAPH_SRC_INTERFACE_SERIALPORTHANDLER_H_
#define LIVEGRAPH_SRC_INTERFACE_SERIALPORTHANDLER_H_

#include <QSerialPort>
#include <QSerialPortInfo>
#include <QQueue>
#include "LiveProtocol.h"
#include "comm_protocol.h"
#include <QTimer>
//#define SIMULATE_SERIAL_INPUT
#ifdef SIMULATE_SERIAL_INPUT
#define SIMULATE_RATE 10

#endif
#ifdef USE_CIRCULAR_BUFFER
#include "boost/circular_buffer.hpp"
#endif
enum SerialPortHandlerState {
    SerialIsOpen,
    SerialReady,
    SerialBusy,
    SerialError,
};

struct LiveData {
    double timestamp;
    float data[6];
};

class SerialMonitor : public QObject {
Q_OBJECT
public:
    SerialMonitor();
    void Start();

    ~SerialMonitor() override;

    void updateBytesCnt(uint32_t cnt);

    void updateFrameCnt(uint32_t msg_id);

    uint32_t getTotalBytes() const;

    uint32_t getTotalFrames() const;

    uint32_t getByteRates() const;

    uint32_t getFrameRates() const;

private slots:

    void BeatPerSec();

private:
    uint32_t total_bytes;
    uint32_t total_frames;
    uint32_t byte_rates;
    uint32_t frame_rates;
    uint32_t total_bytes_last_sec;
    uint32_t total_frame_last_sec;
    std::map<uint32_t, uint32_t> msg_cnt;
    std::map<uint32_t, uint32_t> msg_cnt_last_sec;
    QTimer *timer;
};

class SerialPortHandler : public QObject {
Q_OBJECT
public:
    explicit SerialPortHandler(const QSerialPortInfo &info);
    explicit SerialPortHandler();
    ~SerialPortHandler() override;

public:
    SerialMonitor monitor;

private:
    QSerialPort *serial;
    QSerialPortInfo info;
    std::string filename;
    QSerialPort::BaudRate baud_rate;
    typedef std::function<void(uint32_t,uint8_t *)> callback_type;

public:
    void SetSerial(QSerialPort *serial_);

    void SetInfo(const QSerialPortInfo &info);

    void SetBaudRate(QSerialPort::BaudRate baud_rate);

    bool IsOpen() const;

    /**
     * 给每个消息ID设置回调函数
     * @param id
     * @param callbacks
     */
    void SetCallBackFunc(void *obj,uint32_t id, callback_type callbacks);


private:
    DataHandle handle;


    std::map<uint32_t, callback_type> callback_func = {
            {comm_sync_msg_imu_id,     (callback_type) nullptr},
            {comm_sync_msg_pos_atti_id,(callback_type) nullptr},
    };


#ifdef SIMULATE_SERIAL_INPUT
    QTimer *timer;
    void GenerateSimpleData();
#endif
public:
signals:

    void DataReady(LiveData d);

    void SerialStateChanged(QSerialPort::SerialPortError error);

public slots :

    void handleResults();

    void SerialAct(bool);

    void Init();

    void handleError(QSerialPort::SerialPortError error);

    void Stop();
};

#endif //LIVEGRAPH_SRC_INTERFACE_SERIALPORTHANDLER_H_
